package qc.module.qms.api.job;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import qc.common.core.json.JsonParserUtil;
import qc.common.core.utils.SqlRunnerUtil;
import qc.module.platform.dto.dbTable.DBTableFullDto;
import qc.module.qms.dto.exchange.category.ExchangeCategoryDto;
import qc.module.qms.dto.exchange.ynslt.ExSltPptnRDto;
import qc.module.qms.dto.exchange.ynslt.ExSltRsvrRDto;
import qc.module.qms.dto.station.StationDto;
import qc.module.qms.service.ExchangeCategoryService;
import qc.module.qms.service.ExchangeDataService;
import qc.module.qms.service.QmsStationService;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TransferToYnhjptProcessor
 *
 * @author QuCheng Tech
 * @since 2024/1/29
 */
@Component
public class TransferToYnhjptProcessor implements BasicProcessor {
    @Autowired
    private ExchangeDataService exchangeDataService;

    @Autowired
    private QmsStationService stationService;
    @Autowired
    private ExchangeCategoryService categoryService;

    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private GenerateYnhjptDataProcessor generateYnhjptDataProcessor;
    
    
    //上报数据登录访问token
    //private String accessToken = "";
    
    //报数据登录访问tokenMap
    private Map<String,String> tokenMap = new HashMap<>();

    //静态定义--云南省汇集平台上传数据分类ID集合
    public final int[] ynhjptCategoryIds = new int[]{0x1, 0x2};
    
    @Override
    public ProcessResult process(TaskContext taskContext) throws SQLException {
         System.out.println("====================开始获取上传数据=========================");
         //遍历交换数据分类id集合
        if (ynhjptCategoryIds != null && ynhjptCategoryIds.length > 0x0) {
            for (int categoryId : ynhjptCategoryIds) {
                //获取分类中的站点集合
                List<StationDto> categoryStations = stationService.getByCategoryId(categoryId);
                if (categoryStations != null && categoryStations.size() > 0x0) {
                    //数据分类中有交换站点，判断是否需要处理
                    //获取交换数据分类信息，需要使用其中设置的交换频率等参数
                    ExchangeCategoryDto category = categoryService.get(categoryId);
                    if (category != null && StringUtils.isNotBlank(category.getTablecode())) {
                        //根据数据库表编码获取完整信息，再从信息中获取sql语句、查询数据库连接信息和列信息
                        DBTableFullDto tableFullInfo = generateYnhjptDataProcessor.getDbTableFullInfo(category.getTablecode());
                        //数据库连接信息
                        String dbUrl = "";
                        String dbUser = "";
                        String dbPassword = "";
                        if (tableFullInfo != null) {
                            if (tableFullInfo.getDb() != null) {
                                //解析数据库连接信息
                                String dbConJsonString = tableFullInfo.getDb().getCon();
                                if (StringUtils.isNotBlank(dbConJsonString)) {
                                    //Json对象进行获取
                                    dbUrl = JsonParserUtil.getString(dbConJsonString, "url");
                                    dbUser = JsonParserUtil.getString(dbConJsonString, "user");
                                    dbPassword = JsonParserUtil.getString(dbConJsonString, "password");
                                }
                            }
                        }
                        
                        String sql = "SELECT * FROM " + category.getTablecode() + " WHERE flag=0 AND tm<=? ORDER BY tm ASC";
                        List<Map<String, Object>> queryData = SqlRunnerUtil.selectAll(dbUrl,dbUser,dbPassword,sql,new Date());
                        System.out.println("====================开始处理数据上传=========================");
                        if (categoryId == 0x1){
                            //水库水位
                            //2.1 如果有未上传的水库水位数据，处理并上传
                            handleRsvrDataAndTransferToYnhjpt(queryData,dbUrl,dbUser,dbPassword,category.getTablecode());
                        }else {
                            //降雨量
                            //2.2 如果有未上传的降雨量数据，处理并上传
                            handlePptnDataAndTransferToYnhjpt(queryData,dbUrl,dbUser,dbPassword,category.getTablecode());
                        }
                        
                    }
                }
            }
        }
        
        return new ProcessResult(true,"上传省汇集平台数据成功");
    }

    /**
     * 处理水库水位待上传数据，然后逐条上传到云南汇集平台
     * @param exSltRsvrRData
     */
    private void handleRsvrDataAndTransferToYnhjpt(List<Map<String, Object>> exSltRsvrRData,
                                                   String dbUrl,String dbUser,String dbPassword,String tableCode) throws SQLException {
        //if (StringUtils.isBlank(accessToken)) accessToken = getAccessToken();
        if (CollectionUtils.isNotEmpty(exSltRsvrRData)){
            String appid = null;
            String appkey = null;
            //循环处理水库水位数据
            for (Map<String,Object> dataMap : exSltRsvrRData){
                //处理为要上传的数据格式
                ExSltRsvrRDto exSltRsvrRDto = new ExSltRsvrRDto();
                for (String key:dataMap.keySet()){
                    System.out.println("rsvr:key = " + key + ", value = " + dataMap.get(key));
                    if (key.equals("appid")) if (dataMap.get(key) != null && dataMap.get(key) != "") appid = dataMap.get(key).toString();
                    if (key.equals("appkey")) if (dataMap.get(key) != null && dataMap.get(key) != "") appkey = dataMap.get(key).toString();
                    if (key.equals("rscd")) exSltRsvrRDto.setRscd(dataMap.get(key).toString());
                    if (key.equals("stcd")) exSltRsvrRDto.setStcd(dataMap.get(key).toString());
                    if (key.equals("tm")) exSltRsvrRDto.setTm(dataMap.get(key).toString());
                    if (key.equals("z")) exSltRsvrRDto.setZ(new BigDecimal(dataMap.get(key).toString()));
                    if (key.equals("w")) exSltRsvrRDto.setW(new BigDecimal(dataMap.get(key).toString()));
                    if (key.equals("zrcd")) if (dataMap.get(key) != null && dataMap.get(key) != "") exSltRsvrRDto.setZrcd(dataMap.get(key).toString()); else exSltRsvrRDto.setZrcd("");
                }
                
                //dataMap.forEach((k,v) -> {
                //    System.out.println("rsvr:key = " + k + ", value = " + v);
                //    //if (k.equals("appid")) if (v != null && v != "") appid = v.toString();
                //    //if (k.equals("appkey")) if (v != null && v != "") appkey = v.toString();
                //    
                //    if (k.equals("rscd")) exSltRsvrRDto.setRscd(v.toString());
                //    if (k.equals("stcd")) exSltRsvrRDto.setStcd(v.toString());
                //    if (k.equals("tm")) exSltRsvrRDto.setTm(v.toString());
                //    if (k.equals("z")) exSltRsvrRDto.setZ(new BigDecimal(v.toString()));
                //    if (k.equals("w")) exSltRsvrRDto.setW(new BigDecimal(v.toString()));
                //    if (k.equals("zrcd")) if (v != null && v != "") exSltRsvrRDto.setZrcd(v.toString()); else exSltRsvrRDto.setZrcd("");
                //});

                if (appid == null || appid.equals("")){
                    //没有上传登录参数不处理
                }else{
                    //根据id获取tokenMap中的访问token，如果没有，根据id，key请求token
                    if (tokenMap.get(appid) == null){
                        if (appkey != null && appkey != "") getAccessToken(appid,appkey);
                    }

                    //上传水库水位url
                    String rsvrUrl = "http://112.112.128.35:2355/api/OBZ";
                    //String rsvrUrl = "http://183.224.77.150:2355/api/OBZ";
                    //请求头
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);
                    headers.add("Authorization",tokenMap.get(appid));

                    //请求体
                    HttpEntity<ExSltRsvrRDto> httpEntity = new HttpEntity<>(exSltRsvrRDto,headers);
                    //响应类型
                    ParameterizedTypeReference<String> responseType = new ParameterizedTypeReference<String>() {
                    };
                    //调用上报数据接口上报数据
                    //设置超时时间
                    HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
                    httpRequestFactory.setConnectionRequestTimeout(50*1000);
                    httpRequestFactory.setConnectTimeout(50*1000);
                    httpRequestFactory.setReadTimeout(50*1000);
                    restTemplate.setRequestFactory(httpRequestFactory);
                    ResponseEntity<String> responseEntity = null;
                    try {
                        responseEntity = restTemplate.exchange(rsvrUrl, HttpMethod.POST,httpEntity,responseType);
                    }catch (HttpClientErrorException e){
                        String resBody = e.getResponseBodyAsString();
                        System.out.println("访问上传水库水位接口异常：" + resBody);
                        JSONObject resBodyJsonObject = JSONObject.parseObject(resBody);
                        if (resBodyJsonObject == null){
                            getAccessToken(appid,appkey);
                            System.out.println("异常后重新请求token的id：" + appkey + ", key: " + appkey);
                        }
                    }

                    //解析请求结果
                    if (responseEntity != null){
                        String result = responseEntity.getBody();
                        System.out.println("上传水位数据result：" + result);
                        JSONObject responseJsonObject = JSONObject.parseObject(result);
                        if (responseJsonObject != null){
                            String status = responseJsonObject.getString("status");
                            //如果状态码为401，token无效，重新获取
                            if (status.equals("401")){
                                getAccessToken(appid,appkey);
                            }
                            //如果状态码为200，上传数据成功，修改数据记录：状态为已上传，设置上传时间
                            if (status.equals("200")) {
                                System.out.println("=================修改数据库书库水位数据记录状态================================");
                                String sql = "UPDATE " + tableCode + " SET flag = ?,sendtm = ? WHERE rscd = ? AND stcd = ? AND tm = ?";
                                SqlRunnerUtil.update(dbUrl,dbUser,dbPassword,sql,1,new Date(),exSltRsvrRDto.getRscd(),exSltRsvrRDto.getStcd(),exSltRsvrRDto.getTm());
                            }
                        }
                    }
                }
                
            }
        }
    }

    /**
     * 处理降雨量待上传数据，然后逐条上传到云南汇集平台
     * @param exSltPptnRData
     */
    private void handlePptnDataAndTransferToYnhjpt(List<Map<String, Object>> exSltPptnRData,
                                                   String dbUrl,String dbUser,String dbPassword,String tableCode) throws SQLException {
        //if (StringUtils.isBlank(accessToken)) accessToken = getAccessToken();
        if (CollectionUtils.isNotEmpty(exSltPptnRData)){
            //循环处理降雨量数据
            for (Map<String,Object> dataMap : exSltPptnRData){
                String appid = null;
                String appkey = null;
                //处理为要上传的数据格式
                ExSltPptnRDto exSltPptnRDto = new ExSltPptnRDto();
                for (String key:dataMap.keySet()){
                    System.out.println("pptn:key = " + key + ", value = " + dataMap.get(key));
                    if (key.equals("appid")) if (dataMap.get(key) != null && dataMap.get(key) != "") appid = dataMap.get(key).toString();
                    if (key.equals("appkey")) if (dataMap.get(key) != null && dataMap.get(key) != "") appkey = dataMap.get(key).toString();
                    if (key.equals("stcd")) exSltPptnRDto.setStcd(dataMap.get(key).toString());
                    if (key.equals("tm")) exSltPptnRDto.setTm(dataMap.get(key).toString());
                    if (key.equals("dr")) exSltPptnRDto.setDr(dataMap.get(key).toString());
                    if (key.equals("p")) exSltPptnRDto.setP(new BigDecimal(dataMap.get(key).toString()));
                    if (key.equals("prcd")) if (dataMap.get(key) != null && dataMap.get(key) != "") exSltPptnRDto.setPrcd(dataMap.get(key).toString()); else exSltPptnRDto.setPrcd("");
                }
                //dataMap.forEach((k,v) -> {
                //    System.out.println("pptn:key = " + k + ", value = " + v);
                //    if (k.equals("stcd")) exSltPptnRDto.setStcd(v.toString());
                //    if (k.equals("tm")) exSltPptnRDto.setTm(v.toString());
                //    if (k.equals("dr")) exSltPptnRDto.setDr(v.toString());
                //    if (k.equals("p")) exSltPptnRDto.setP(new BigDecimal(v.toString()));
                //    if (k.equals("prcd")) if (v != null && v != "") exSltPptnRDto.setPrcd(v.toString()); else exSltPptnRDto.setPrcd("");
                //});

                //根据id获取tokenMap中的访问token，如果没有，根据id，key请求token

                if (appid == null || appid.equals("")){
                    //没有上传登录参数不处理
                }else{
                    //根据id获取tokenMap中的访问token，如果没有，根据id，key请求token
                    if (tokenMap.get(appid) == null) {
                        if (appkey != null && appkey != "") getAccessToken(appid, appkey);
                    }

                    //上传降雨量url
                    String pptnUrl = "http://112.112.128.35:2355/api/OBP";
                    //String pptnUrl = "http://183.224.77.150:2355/api/OBP";
                    //请求头
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);
                    headers.add("Authorization",tokenMap.get(appid));

                    //请求体
                    HttpEntity<ExSltPptnRDto> httpEntity = new HttpEntity<>(exSltPptnRDto,headers);
                    //响应类型
                    ParameterizedTypeReference<String> responseType = new ParameterizedTypeReference<String>() {
                    };
                    //调用上报数据接口上报数据
                    //设置超时时间
                    HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
                    httpRequestFactory.setConnectionRequestTimeout(50*1000);
                    httpRequestFactory.setConnectTimeout(50*1000);
                    httpRequestFactory.setReadTimeout(50*1000);
                    restTemplate.setRequestFactory(httpRequestFactory);
                    ResponseEntity<String> responseEntity = null;
                    try {
                        responseEntity = restTemplate.exchange(pptnUrl, HttpMethod.POST,httpEntity,responseType);
                    }catch (HttpClientErrorException e){
                        String resBody = e.getResponseBodyAsString();
                        System.out.println("访问上传将降雨量接口异常：" + resBody);
                        JSONObject resBodyJsonObject = JSONObject.parseObject(resBody);
                        if (resBodyJsonObject == null){
                            getAccessToken(appid,appkey);
                            System.out.println("异常后重新请求token的id：" + appkey + ", key: " + appkey);
                        }
                    }
                    //解析请求结果
                    if (responseEntity != null){
                        String result = responseEntity.getBody();
                        System.out.println("上传降雨量数据result：" + result);
                        JSONObject responseJsonObject = JSONObject.parseObject(result);
                        if (responseJsonObject != null){
                            String status = responseJsonObject.getString("status");
                            //如果状态码为401，token无效，重新获取
                            if (status.equals("401")) {
                                getAccessToken(appid,appkey);
                            }
                            //如果状态码为200，上传数据成功，修改数据记录：状态为已上传，设置上传时间
                            if (status.equals("200")) {
                                System.out.println("=================修改数据库降雨量数据记录状态================================");
                                String sql = "UPDATE " + tableCode + " SET flag = ?,sendtm = ? WHERE stcd = ? AND tm = ?";
                                SqlRunnerUtil.update(dbUrl,dbUser,dbPassword,sql,1,new Date(),exSltPptnRDto.getStcd(),exSltPptnRDto.getTm());
                            }
                        }
                    }
                }
                
            }
        }
    }

    /**
     * 获取登录access_token
     * @param id 登录请求参数id
     * @param key 登录请求参数key
     */
    private void getAccessToken(String id,String key){
        String token = "";
        String url = "http://112.112.128.35:2355/api/login";
        //String url = "http://183.224.77.150:2355/api/login";
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        
        //请求参数
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id",id);
        jsonObject.put("key",key);

        //请求体
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(jsonObject,headers);
        //响应类型
        ParameterizedTypeReference<String> responseType = new ParameterizedTypeReference<String>() {
        };
        //调用上报数据接口上报数据
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST,httpEntity,responseType);

        System.out.println(responseEntity);
        //解析请求结果
        String result = responseEntity.getBody();
        JSONObject responseJsonObject = JSONObject.parseObject(result);
        if (responseJsonObject != null){
            String status = responseJsonObject.getString("status");
            if (status.equals("200")){
                token = responseJsonObject.getString("access_token");
            }

        }
        tokenMap.put(id,"Bearer " + token);
    }
}
